# -*- coding: utf-8 -*-
#
# Copyright (c) 2008 European Southern Observatory, European Space Agency (ESO/ESA)
# 
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# 
#     * Redistributions of source code must retain the above copyright
#       notice, this list of conditions and the following disclaimer.
# 
#     * Redistributions in binary form must reproduce the above copyright
#       notice, this list of conditions and the following disclaimer in the
#       documentation and/or other materials provided with the distribution.
# 
#     * Neither the name of the European Southern Observatory, European Space 
#       Agency nor the names of its contributors may be used to endorse or 
#       promote products derived from this software without specific prior 
#       written permission.
# 
# THIS SOFTWARE IS PROVIDED BY ESO/ESA AND ``AS IS'' AND ANY EXPRESS OR IMPLIED
# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
# EVENT SHALL ESA/ESO BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
# IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE

from ConfigParser import ConfigParser
from pkg_resources import resource_filename, Requirement
from socket import gethostname
import os
from django.core.exceptions import ImproperlyConfigured

__all__ = ['locate_ini_config']

def dyn_import(name):
    mod = __import__(name)
    components = name.split('.')
    for comp in components[1:]:
        mod = getattr(mod, comp)
    return mod

def _try_config_read( filename, base ):
    if os.path.isfile( filename ):
        try:
            if not base:
                base = ''
            config = ConfigParser( {'PRJBASE' : base } )
            config.read( filename )
        except Exception:
            config = None
            
        if config is not None:
            raise config

def _try_package_resources( module, base, ininames, dirs ):
    # Search directly in egg resource dir
    for d in dirs:
        for n in ininames:
            filename = resource_filename( Requirement.parse( module ), d + n )
            _try_config_read( filename, base )
            
def _try_project_base( base, ininames, dirs ):
    if base:
        for d in dirs:
            for n in ininames:
                filename = os.path.join( base, os.path.join( d, n ) )
                _try_config_read( filename, base )

def _try_etc( base, ininames ):
    for n in ininames:
        filename = os.path.join( "/etc", n )
        _try_config_read( filename, base )
        
def _determine_prjbase( project_module, hostname ):
    try:
        mod = __import__( project_module )
        PROJECT_BASES = mod.PROJECT_BASES
        
        if mod.PROJECT_BASES.has_key( hostname ):
            bases = PROJECT_BASES[hostname]
        elif mod.PROJECT_BASES.has_key( '_default' ):
            bases = PROJECT_BASES['_default']
            
        for b in bases:
            if os.path.isdir( b ):
                return b
    except ImportError:
        return None

    return None

def locate_ini_config( project_module, fname = "settings" ):
    """
    Locate settings.ini file
    """
    hostname = gethostname()
    ininames = [ "%s-%s.ini" % (fname, hostname), "%s.ini" % fname ]
    dirs = [ "conf/", "", ]
    base = _determine_prjbase( project_module, hostname )
      
    if os.environ.has_key( 'DJANGO_SETTINGS_INI' ):
        ininames = [ os.environ['DJANGO_SETTINGS_INI'], ]

    try:
        _try_package_resources( project_module, base, ininames, dirs )
        _try_project_base( base, ininames, dirs )
        _try_etc( base, ininames )
    except ConfigParser, config:
        return config
    
    raise ImproperlyConfigured('Settings file named %s could not be found using project base %s.' % ( str( ininames ), base ) )
